unit frmSearchDialog;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  ExtCtrls, StdCtrls, frmEditor, SynEditTypes;

type TSearchType = (stFind, stReplace, stReplaceAll);

type

  { TSearchDialog }

  TSearchDialog = class(TForm)
    btnClose: TButton;
    btnFind: TButton;
    btnReplace: TButton;
    btnReplaceAll: TButton;
    Image1: TImage;
    SearchMessage: TLabel;
    Panel1: TPanel;
    ReplaceText: TLabeledEdit;
    SearchOptions: TCheckGroup;
    SearchText: TLabeledEdit;
    procedure btnCloseClick(Sender: TObject);
    procedure btnFindClick(Sender: TObject);
    procedure btnReplaceAllClick(Sender: TObject);
    procedure btnReplaceClick(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormHide(Sender: TObject);
    procedure ReplaceTextChange(Sender: TObject);
    procedure SearchOptionsItemClick(Sender: TObject; Index: integer);
  private
    FEditor: TEditorFrame;
    FSearchOptions: TSynSearchOptions;
    procedure SetEditor(const AValue: TEditorFrame);
    procedure EnableOrDisableButtons;
    procedure Execute(const ASearchType: TSearchType);
  public
    property Editor: TEditorFrame read FEditor write SetEditor;
  end; 

var
  SearchDialog: TSearchDialog;

implementation

uses dmMain, frmMain;

{ TSearchDialog }

procedure TSearchDialog.ReplaceTextChange(Sender: TObject);
begin
  EnableOrDisableButtons;
end;

procedure TSearchDialog.btnFindClick(Sender: TObject);
begin
  Execute(stFind);
end;

procedure TSearchDialog.btnCloseClick(Sender: TObject);
begin
  Close;
end;

procedure TSearchDialog.btnReplaceAllClick(Sender: TObject);
begin
  Execute(stReplaceAll);
end;

procedure TSearchDialog.btnReplaceClick(Sender: TObject);
begin
  Execute(stReplace);
end;

procedure TSearchDialog.FormActivate(Sender: TObject);
begin
  SearchMessage.Visible := False;
  SearchText.SetFocus;
end;

procedure TSearchDialog.FormCreate(Sender: TObject);
var i : Integer;
begin
  for i := 0 to SearchOptions.Items.Count - 1 do
    SearchOptions.Checked[i] := dataMain.GetApplicationSetting('SearchPreferences/' + StringReplace(SearchOptions.Items[i], ' ', '', [rfReplaceAll]), False);
end;

procedure TSearchDialog.FormHide(Sender: TObject);
begin
  MainForm.SetFocus;
end;

procedure TSearchDialog.SearchOptionsItemClick(Sender: TObject; Index: integer);
var Option: TSynSearchOption;
begin
  dataMain.SetApplicationSetting('SearchPreferences/' + StringReplace(SearchOptions.Items[Index], ' ', '', [rfReplaceAll]), SearchOptions.Checked[Index]);
  case Index of
    0: Option := ssoMatchCase; // Match case
    1: Option := ssoWholeWord; // Match whole words
    2: Option := ssoSelectedOnly; // Only search selection
    3: Option := ssoPrompt;    // Prompt before replacing
    4: Option := ssoRegExpr;   // Search using regular expression
  end;
  if SearchOptions.Checked[Index] then
    Include(FSearchOptions, Option)
  else
    Exclude(FSearchOptions, Option);
end;

procedure TSearchDialog.SetEditor(const AValue: TEditorFrame);
begin
  FEditor := AValue;
  EnableOrDisableButtons;
end;

procedure TSearchDialog.EnableOrDisableButtons;
begin
  btnFind.Enabled := Assigned(Editor);
  btnReplace.Enabled := Assigned(Editor) and (ReplaceText.Text <> '');
  btnReplaceAll.Enabled := Assigned(Editor) and (ReplaceText.Text <> '');
end;

procedure TSearchDialog.Execute(const ASearchType: TSearchType);
var result : Integer;
begin
  SearchMessage.Visible := False;
  if not Assigned(Editor) then Exit;
  FSearchOptions := FSearchOptions - [ssoReplace, ssoReplaceAll];
  if ASearchType = stReplace then Include(FSearchOptions, ssoReplace);
  if ASearchType = stReplaceAll then Include(FSearchOptions, ssoReplaceAll);
  result := Editor.seEditor.SearchReplace(SearchText.Text, ReplaceText.Text, FSearchOptions);
  if result = 0 then
  begin
    SearchMessage.Caption := 'No results found, started the search from the top of the file.';
    if(0 = Editor.seEditor.SearchReplaceEx(SearchText.Text, ReplaceText.Text, FSearchOptions, Point(0, 0))) then
       SearchMessage.Caption := 'Searched the entire file, but found no results.';
    SearchMessage.Visible := True;
  end;
end;

initialization
  {$I frmSearchDialog.lrs}

end.

